package com.zdb.n1.service.impl;

import com.zdb.n1.entity.ExerciseRecord;
import com.zdb.n1.entity.FitnessGoal;
import com.zdb.n1.entity.User;
import com.zdb.n1.payload.response.RankingResponse;
import com.zdb.n1.repository.ExerciseRecordRepository;
import com.zdb.n1.repository.FitnessGoalRepository;
import com.zdb.n1.repository.UserRepository;
import com.zdb.n1.service.StatisticsService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class StatisticsServiceImpl implements StatisticsService {

    private final UserRepository userRepository;
    private final ExerciseRecordRepository exerciseRecordRepository;
    private final FitnessGoalRepository fitnessGoalRepository;

    @Override
    public List<RankingResponse> getRankings(String type, int limit, String timeRange) {
        // 根据类型获取不同的排行榜
        switch (type.toUpperCase()) {
            case "DURATION":
                return getDurationRankings(limit, timeRange);
            case "CALORIES":
                return getCaloriesRankings(limit, timeRange);
            case "GOAL_COMPLETION":
                return getGoalCompletionRankings(limit, timeRange);
            default:
                return getDurationRankings(limit, timeRange);
        }
    }

    private List<RankingResponse> getDurationRankings(int limit, String timeRange) {
        // 获取所有用户
        List<User> users = userRepository.findAll();
        
        // 获取时间范围
        Date rangeStartDate = getTimeRangeStartDate(timeRange);
        
        // 获取指定时间范围内所有用户的运动记录
        List<ExerciseRecord> allRecords = exerciseRecordRepository.findByStartTimeAfter(rangeStartDate);
        
        // 按用户ID分组，计算每个用户的总运动时长
        Map<Long, Double> userDurations = new HashMap<>();
        for (ExerciseRecord record : allRecords) {
            Long userId = record.getUser().getId();
            double duration = record.getDurationMinutes() != null ? record.getDurationMinutes() : 0;
            userDurations.put(userId, userDurations.getOrDefault(userId, 0.0) + duration);
        }
        
        // 构建排行榜响应
        List<RankingResponse> rankings = new ArrayList<>();
        for (User user : users) {
            Double duration = userDurations.getOrDefault(user.getId(), 0.0);
            if (duration > 0) {
                rankings.add(RankingResponse.builder()
                        .userId(user.getId())
                        .username(user.getUsername())
                        .value(duration)
                        .valueLabel(String.format("%.0f分钟", duration))
                        .build());
            }
        }
        
        // 排序
        rankings.sort(Comparator.comparing(RankingResponse::getValue).reversed());
        
        // 添加排名
        for (int i = 0; i < rankings.size(); i++) {
            rankings.get(i).setRank(i + 1);
        }
        
        // 限制返回数量
        return rankings.stream().limit(limit).collect(Collectors.toList());
    }
    
    private List<RankingResponse> getCaloriesRankings(int limit, String timeRange) {
        // 获取所有用户
        List<User> users = userRepository.findAll();
        
        // 获取时间范围
        Date rangeStartDate = getTimeRangeStartDate(timeRange);
        
        // 获取指定时间范围内所有用户的运动记录
        List<ExerciseRecord> allRecords = exerciseRecordRepository.findByStartTimeAfter(rangeStartDate);
        
        // 按用户ID分组，计算每个用户的总卡路里消耗
        Map<Long, Double> userCalories = new HashMap<>();
        for (ExerciseRecord record : allRecords) {
            Long userId = record.getUser().getId();
            double calories = record.getCaloriesBurned() != null ? record.getCaloriesBurned() : 0;
            userCalories.put(userId, userCalories.getOrDefault(userId, 0.0) + calories);
        }
        
        // 构建排行榜响应
        List<RankingResponse> rankings = new ArrayList<>();
        for (User user : users) {
            Double calories = userCalories.getOrDefault(user.getId(), 0.0);
            if (calories > 0) {
                rankings.add(RankingResponse.builder()
                        .userId(user.getId())
                        .username(user.getUsername())
                        .value(calories)
                        .valueLabel(String.format("%.0f卡路里", calories))
                        .build());
            }
        }
        
        // 排序
        rankings.sort(Comparator.comparing(RankingResponse::getValue).reversed());
        
        // 添加排名
        for (int i = 0; i < rankings.size(); i++) {
            rankings.get(i).setRank(i + 1);
        }
        
        // 限制返回数量
        return rankings.stream().limit(limit).collect(Collectors.toList());
    }
    
    private List<RankingResponse> getGoalCompletionRankings(int limit, String timeRange) {
        // 获取所有用户
        List<User> users = userRepository.findAll();
        
        // 获取时间范围
        Date rangeStartDate = getTimeRangeStartDate(timeRange);
        LocalDateTime rangeStart = LocalDateTime.ofInstant(rangeStartDate.toInstant(), ZoneId.systemDefault());
        
        // 获取所有用户的目标
        List<FitnessGoal> allGoals = fitnessGoalRepository.findAll();
        
        // 过滤出时间范围内的目标
        List<FitnessGoal> filteredGoals = allGoals.stream()
                .filter(goal -> {
                    LocalDateTime goalDate = goal.getCompletedDate() != null ? 
                            goal.getCompletedDate() : goal.getStartDate();
                    return goalDate != null && goalDate.isAfter(rangeStart);
                })
                .collect(Collectors.toList());
        
        // 按用户ID分组，计算每个用户的目标完成率
        Map<Long, List<FitnessGoal>> userGoalsMap = new HashMap<>();
        for (FitnessGoal goal : filteredGoals) {
            Long userId = goal.getUser().getId();
            if (!userGoalsMap.containsKey(userId)) {
                userGoalsMap.put(userId, new ArrayList<>());
            }
            userGoalsMap.get(userId).add(goal);
        }
        
        // 构建排行榜响应
        List<RankingResponse> rankings = new ArrayList<>();
        for (User user : users) {
            List<FitnessGoal> userGoals = userGoalsMap.getOrDefault(user.getId(), Collections.emptyList());
            if (!userGoals.isEmpty()) {
                // 计算目标完成率 - 修改这里，使用status字段来检查目标是否已完成
                long completedGoals = userGoals.stream()
                        .filter(goal -> goal.getStatus() == FitnessGoal.GoalStatus.COMPLETED)
                        .count();
                double completionRate = (double) completedGoals / userGoals.size() * 100;
                
                rankings.add(RankingResponse.builder()
                        .userId(user.getId())
                        .username(user.getUsername())
                        .value(completionRate)
                        .valueLabel(String.format("%.1f%%", completionRate))
                        .build());
            }
        }
        
        // 排序
        rankings.sort(Comparator.comparing(RankingResponse::getValue).reversed());
        
        // 添加排名
        for (int i = 0; i < rankings.size(); i++) {
            rankings.get(i).setRank(i + 1);
        }
        
        // 限制返回数量
        return rankings.stream().limit(limit).collect(Collectors.toList());
    }
    
    /**
     * 根据时间范围类型获取起始时间
     * @param timeRange 时间范围类型：DAY(日榜)、WEEK(周榜)、MONTH(月榜)、YEAR(年榜)
     * @return 起始时间
     */
    private Date getTimeRangeStartDate(String timeRange) {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime startDate;
        
        switch (timeRange.toUpperCase()) {
            case "DAY":
                // 今天凌晨开始
                startDate = now.truncatedTo(ChronoUnit.DAYS);
                break;
            case "WEEK":
                // 本周开始
                startDate = now.minus(now.getDayOfWeek().getValue() - 1, ChronoUnit.DAYS)
                        .truncatedTo(ChronoUnit.DAYS);
                break;
            case "MONTH":
                // 本月开始
                startDate = now.withDayOfMonth(1).truncatedTo(ChronoUnit.DAYS);
                break;
            case "YEAR":
                // 本年开始
                startDate = now.withDayOfYear(1).truncatedTo(ChronoUnit.DAYS);
                break;
            default:
                // 默认30天
                startDate = now.minus(30, ChronoUnit.DAYS);
        }
        
        return Date.from(startDate.atZone(ZoneId.systemDefault()).toInstant());
    }
} 